package com.kuangstudy.service.pv;

import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import java.util.Iterator;
import java.util.Map;

/**
 * @author 飞哥
 * @Title: 学相伴出品
 * @Description: 我们有一个学习网站：https://www.kuangstudy.com
 * @date 2021/5/20 15:46
 */
@Service
@Log4j2
public class SecondCacheBbsPvService {

    @Autowired
    private RedisTemplate redisTemplate;

    @PostConstruct
    public void cacheTask() {
        log.info("二级缓存cache：开始弹出每篇文章进行数据库的同步和文章数量的累加...");
        new Thread(() -> runTwoCache()).start();
    }

    /*
     * 二级缓存定时消费：
     * 定时器，每隔6分钟，从redis的list数据结构中pop弹出Map<文章id,文章pv>。弹出来的目的是：
     * 1：把Map<文章ID，文章pv> 保存到数据库中
     * 2：把Map<文章ID，文章pv> 同步到redis的缓存计数器中注意调用的incrby key 文章pv
     *
     * list存储的数据结构是每个list元素存储的是：Map<文章ID,pv数量>即每个时间块的PV数据。
     **/
    public void runTwoCache() {
        while (true) {
            while (this.popbbs()) {

            }
            // 开始
            try {
                // 每个2分钟执行一次同步，如果是生成环境建议是6分钟，时间一定要大于前面的一级缓存消费的时间
                Thread.sleep(1000 * 60 * 2);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            log.info("二级缓存定时器消费，定时刷新开始......");
        }
    }


    /**
     * @return void
     * @Author 徐柯
     * @Description 具体每篇文章计数开始
     * @Date 15:50 2021/5/20
     * @Param [bbsid]
     **/
    public boolean popbbs() {
        ListOperations<String, Map<Integer, Integer>> listOperations = this.redisTemplate.opsForList();
        Map<Integer, Integer> rightPopMap = listOperations.rightPop(BbsPvServiceConstants.CACHE_ONE_PV_LIST);
        log.info("弹出来的元素是: {}", rightPopMap);
        // 1: 如果没有需要同步的数据，直接返回false
        if (CollectionUtils.isEmpty(rightPopMap)) {
            return false;
        }

        // 2：如果二级缓存中存在需要同步的数据开始存入到数据库中
        // todo: 将每篇文章的数量同步到数据库中

        // 3：如果二级缓存中存在需要同步的数据开始存入到数据库中
        for (Map.Entry<Integer, Integer> integerIntegerEntry : rightPopMap.entrySet()) {
            // 4:开始找到每篇文章的对应的 pv浏览数同步到redis中
            String key = BbsPvServiceConstants.CACHE_SECOND_PV_LIST + integerIntegerEntry.getKey();
            // 5: 调用redis的incrby key pvdata进行pv同步
            this.redisTemplate.opsForValue().increment(key, integerIntegerEntry.getValue());
        }

        return true;

    }

}
